Various forms of network storage systems are known today. These forms include network attached storage (NAS), storage area networks (SANs), and others. Network storage systems are commonly used for a variety of purposes, such as providing multiple users with access to shared data, backing up critical data (e.g., by data mirroring), etc.
A network storage system can include at least one storage system, which is a processing system configured to store and retrieve data on behalf of one or more storage client processing systems (“clients”). In the context of NAS, a storage system may be a file server, which is sometimes called a “filer”. A filer operates on behalf of one or more clients to store and manage shared files in a set of mass storage devices, such as magnetic or optical disks or tapes, or flash drives. The mass storage devices may be organized into one or more volumes of a Redundant Array of Inexpensive Disks (RAID). In a SAN context, the storage server provides clients with block-level access to stored data, rather than file-level access. Some storage servers are capable of providing clients with both file-level access and block-level access.
A RAID group may include an array of mass storage devices with data from a filesystem stored across the mass storage devices in stripes. During configuration, storage spaces on each of the storage devices are divided into data units formed by a contiguous set of data blocks. A RAID group is then created by selecting blocks across the set of storage devices, and grouping the selected blocks as a “parity group”. An array of storage devices can be configured with multiple parity groups. The array can then be presented as a single storage drive to external systems, and each of the parity groups can be seen as a contiguous storage unit. Since extra disks can be used to offload some of the I/O traffic from disks participating in the reconstruction of a parity group, the read and write bandwidth bottlenecks commonly associated with traditional RAID implementations may be reduced.
Parity declustering may also be implemented in the array to further improve performance and recovery times. With parity declustering, parity groups are distributed across disks to produce a balanced I/O load on surviving disks. However, several challenges exist with conventional techniques for balancing I/O load across disks during reconstruction. In particular, conventional techniques for generating a declustered layout use a static approach which enforces a restriction of the same stripe width (i.e., the number of mass storage devices in the RAID group) and RAID scheme on parity groups in the array to ensure a balanced distribution. Declustering parity groups with different RAID schemes or different stripe widths to facilitate particular storage requirements is not viable.
As the amount of storage needed by the filesystem increases or decreases, it may become necessary to add or remove a mass storage device from the RAID group. Such modifications may also include adding a disk to the array, logically partitioning disk space into various sized “containers” constituting parity groups, resizing containers, manually rebalancing storage resources to service more frequently accessed data (“hot data”), etc. In a traditional RAID group based organization, addition of mass storage devices to a RAID group causes the stripe-width to increase. Once the stripe-width reaches a predetermined maximum size, the addition of a new mass storage device causes the creation of a new RAID group. If the filesystem was already fairly full, then subsequent data allocation is confined to the newly added mass storage devices. If the newly added mass storage devices are few in number, then it would result in sub-optimal read performance, as the uniform characteristics of the parity groups are affected thereby changing the distribution of I/O traffic, including reconstruction load, offloaded to the surviving disks.